#include "stdafx.h"
#include "BoundingSphere.h"

using namespace mmath;

BoundingSphere::BoundingSphere()
{

}

BoundingSphere::BoundingSphere(const XMFLOAT3 & center, float radius)
{
	Center = center;
	Radius = radius;
}

BoundingSphere::BoundingSphere(const byte * verts, uint numVerts, uint stride)
{
	construct(verts, numVerts, stride);
}


bool BoundingSphere::intersects( const BoundingSphere & other )
{
	return XMVectorGetX(XMVector3Length(XMVectorSubtract(XMLoadFloat3(&Center), XMLoadFloat3(&other.Center)))) <= Radius + other.Radius;
}


// stride - size in bytes of entire vertex struct
void BoundingSphere::construct(const byte * verts, uint numVerts, uint stride)
{
	XMVECTOR sum = XMVectorZero();
	for (uint i = 0; i < numVerts ; i++)
	{
		sum = XMVectorAdd(sum, XMLoadFloat3((XMFLOAT3*)&verts[i * stride]));
	}

	XMVECTOR center = XMVectorDivide(sum, XMVectorReplicate((float)numVerts));

	float radiusSquared = 0.f;
	for (uint i = 0; i < numVerts ; i++)
	{
		float dist = XMVectorGetX( XMVector3LengthSq( XMVectorSubtract(XMLoadFloat3((XMFLOAT3*)&verts[i * stride]), center) ) );
		if(dist > radiusSquared)
			radiusSquared = dist;
	}

	XMStoreFloat3(&Center, center);
	Radius = sqrtf(radiusSquared);
}

BoundingSphere BoundingSphere::transform(const BoundingSphere & sphere, const XMVECTOR & translation, const XMVECTOR & orientation, const XMVECTOR & scale)
{
	//XMFLOAT3 center;
	//XMVECTOR xmCenter = XMLoadFloat3(&sphere.Center);

	//XMVECTOR point = XMVectorAdd(xmCenter, XMVectorSet(sphere.Radius, 0, 0, 0));
	//point = XMVector3Transform(point, xform);

	//xmCenter = XMVector3Transform(xmCenter, xform);
	//XMStoreFloat3(&center, xmCenter);

	//return BoundingSphere(center, XMVectorGetX( XMVector3Length( XMVectorSubtract(point, xmCenter) ) )); // UNIFORM SCALING ASSUMED!!!

	float maxScale = (std::max)(XMVectorGetX(scale), XMVectorGetY(scale));
	maxScale = (std::max)(XMVectorGetZ(scale), maxScale);
	
	XMVECTOR center = XMLoadFloat3(&sphere.Center);
	center = XMVectorMultiply(center, scale);
	center = XMVector3Rotate(center, orientation);
	center = XMVectorAdd(center, translation);

	XMFLOAT3 tmpCenter;
	XMStoreFloat3(&tmpCenter, center);

	float radius = sphere.Radius * maxScale;

	return BoundingSphere(tmpCenter, radius);
}

BoundingSphere BoundingSphere::transform( const BoundingSphere & sphere, const XMVECTOR & translation, const XMVECTOR & orientation, float scale )
{
	XMVECTOR center = XMLoadFloat3(&sphere.Center);
	center = XMVectorMultiply(center, XMVectorReplicate(scale));
	center = XMVector3Rotate(center, orientation);
	center = XMVectorAdd(center, translation);

	XMFLOAT3 tmpCenter;
	XMStoreFloat3(&tmpCenter, center);

	float radius = sphere.Radius * scale;

	return BoundingSphere(tmpCenter, radius);
}
